/*
 *  Copyright (c) 2023-2025, Agents-Flex (fuhai999@gmail.com).
 *  <p>
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *  <p>
 *  http://www.apache.org/licenses/LICENSE-2.0
 *  <p>
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.agentsflex.core.util;

import com.agentsflex.core.llm.functions.Function;
import com.agentsflex.core.llm.functions.McpToolFunction;
import com.agentsflex.core.llm.functions.Parameter;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.noear.solon.ai.chat.tool.FunctionTool;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

public class McpToolCallUtil {


    private static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 将 JSON Schema 转换为 Parameter 列表
     */
    public static List<Parameter> convert(String jsonSchema) {
        try {
            JsonNode schemaNode = objectMapper.readTree(jsonSchema);
            return convertSchemaToParameters(schemaNode);
        } catch (Exception e) {
            throw new RuntimeException("Failed to convert JSON Schema to Parameters", e);
        }
    }

    /**
     * 递归转换 JSON Schema 节点为 Parameter 列表
     */
    private static List<Parameter> convertSchemaToParameters(JsonNode schemaNode) {
        List<Parameter> parameters = new ArrayList<>();

        // 处理对象类型的属性
        if (schemaNode.has("properties") && schemaNode.get("properties").isObject()) {
            ObjectNode properties = (ObjectNode) schemaNode.get("properties");
            List<String> requiredFields = getRequiredFields(schemaNode);
            for (Map.Entry<String, JsonNode> field : properties.properties()) {
                String fieldName = field.getKey();
                JsonNode fieldSchema = field.getValue();

                Parameter parameter = convertFieldToParameter(fieldName, fieldSchema, requiredFields);
                parameters.add(parameter);
            }
        } else if (schemaNode.has("items")) {
            // 处理数组类型的 items
            JsonNode itemsSchema = schemaNode.get("items");
            // 如果数组项是对象，递归处理其属性
            if (itemsSchema.has("properties")) {
                return convertSchemaToParameters(itemsSchema);
            }
            // 如果数组项是基本类型，创建一个 name 为 null 的 Parameter
            else {
                Parameter arrayItemParam = createArrayItemParameter(itemsSchema);
                parameters.add(arrayItemParam);
            }
        }
        return parameters;
    }

    /**
     * 创建数组项的 Parameter（name 为 null）
     */
    private static Parameter createArrayItemParameter(JsonNode itemSchema) {
        Parameter param = new Parameter();
        param.setName(null); // name 为 null
        param.setType(getTypeFromSchema(itemSchema));

        // 设置描述（只保留基本描述）
        if (itemSchema.has("description")) {
            param.setDescription(itemSchema.get("description").asText());
        } else if (itemSchema.has("title")) {
            param.setDescription(itemSchema.get("title").asText());
        }

        // 处理枚举值
        setEnumsFromSchema(param, itemSchema);

        // 如果数组项本身是对象，递归处理
        if ("object".equals(param.getType()) && itemSchema.has("properties")) {
            List<Parameter> children = convertSchemaToParameters(itemSchema);
            param.setChildren(children);
        }
        // 如果数组项本身是数组，递归处理嵌套数组
        else if ("array".equals(param.getType()) && itemSchema.has("items")) {
            handleArrayType(param, itemSchema);
        }

        return param;
    }

    /**
     * 从 JsonNode 中提取枚举值并设置到 Parameter 中
     */
    private static void setEnumsFromSchema(Parameter param, JsonNode schema) {
        if (schema.has("enum")) {
            ArrayNode enumArray = (ArrayNode) schema.get("enum");
            String[] enums = new String[enumArray.size()];
            for (int i = 0; i < enumArray.size(); i++) {
                enums[i] = enumArray.get(i).asText();
            }
            param.setEnums(enums);
        }
    }

    /**
     * 将单个字段转换为 Parameter
     */
    private static Parameter convertFieldToParameter(String fieldName, JsonNode fieldSchema, List<String> requiredFields) {
        Parameter parameter = new Parameter();
        parameter.setName(fieldName);

        // 设置类型
        String type = getTypeFromSchema(fieldSchema);
        parameter.setType(type);

        // 设置描述（只保留基本描述）
        if (fieldSchema.has("description")) {
            parameter.setDescription(fieldSchema.get("description").asText());
        } else if (fieldSchema.has("title")) {
            parameter.setDescription(fieldSchema.get("title").asText());
        }

        // 设置是否必填
        parameter.setRequired(requiredFields.contains(fieldName));

        // 处理枚举值
        setEnumsFromSchema(parameter, fieldSchema);

        // 处理对象类型的子属性
        if ("object".equals(type) && fieldSchema.has("properties")) {
            List<Parameter> children = convertSchemaToParameters(fieldSchema);
            parameter.setChildren(children);
        }

        // 处理数组类型
        if ("array".equals(type) && fieldSchema.has("items")) {
            handleArrayType(parameter, fieldSchema);
        }

        return parameter;
    }

    /**
     * 处理数组类型
     */
    private static void handleArrayType(Parameter parameter, JsonNode fieldSchema) {
        if (fieldSchema.has("items")) {
            JsonNode itemsSchema = fieldSchema.get("items");

            // 如果数组项是对象
            if (itemsSchema.has("properties")) {
                List<Parameter> itemParameters = convertSchemaToParameters(itemsSchema);
                parameter.setChildren(itemParameters);
            }
            // 如果数组项是基本类型或数组，创建 name 为 null 的 Parameter
            else {
                Parameter itemParam = createArrayItemParameter(itemsSchema);
                List<Parameter> children = new ArrayList<>();
                children.add(itemParam);
                parameter.setChildren(children);

                // 递归处理嵌套数组
                if ("array".equals(itemParam.getType()) && itemsSchema.has("items")) {
                    handleArrayType(itemParam, itemsSchema);
                }
            }
        }
    }

    /**
     * 从 Schema 中获取类型
     */
    private static String getTypeFromSchema(JsonNode schema) {
        if (schema.has("type")) {
            return schema.get("type").asText();
        }
        // 根据其他属性推断类型
        if (schema.has("properties")) {
            return "object";
        }
        if (schema.has("items")) {
            return "array";
        }
        return "string";
    }

    /**
     * 获取必填字段列表
     */
    private static List<String> getRequiredFields(JsonNode schema) {
        List<String> requiredFields = new ArrayList<>();
        if (schema.has("required") && schema.get("required").isArray()) {
            ArrayNode requiredArray = (ArrayNode) schema.get("required");
            for (JsonNode requiredField : requiredArray) {
                requiredFields.add(requiredField.asText());
            }
        }
        return requiredFields;
    }


    public static List<Function> convertToFunctions(Collection<FunctionTool> functionTools) {
        List<Function> functions = new ArrayList<>();
        for (FunctionTool functionTool : functionTools) {
            functions.add(convertToFunction(functionTool));
        }
        return functions;
    }

    public static Function convertToFunction(FunctionTool functionTool) {
        return new McpToolFunction(functionTool);
    }
}
